///*
// * Copyright 2002-2022 the original author or authors.
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// *      https://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//
//package com.elite.security.web;
//
//import java.util.*;
//import java.util.stream.Collectors;
//
//import com.elite.security.customizer.CustomWebSecurityCustomizer;
//import jakarta.servlet.DispatcherType;
//import jakarta.servlet.Filter;
//
//import org.springframework.beans.factory.BeanClassLoaderAware;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
//import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
//import org.springframework.boot.autoconfigure.security.SecurityProperties;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.DependsOn;
//import org.springframework.context.annotation.ImportAware;
//import org.springframework.core.OrderComparator;
//import org.springframework.core.Ordered;
//import org.springframework.core.annotation.AnnotationAttributes;
//import org.springframework.core.annotation.AnnotationUtils;
//import org.springframework.core.annotation.Order;
//import org.springframework.core.type.AnnotationMetadata;
//import org.springframework.security.access.expression.SecurityExpressionHandler;
//import org.springframework.security.config.Customizer;
//import org.springframework.security.config.annotation.ObjectPostProcessor;
//import org.springframework.security.config.annotation.SecurityConfigurer;
//import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.config.annotation.web.builders.WebSecurity;
//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
//import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
//import org.springframework.security.config.crypto.RsaKeyConversionServicePostProcessor;
//import org.springframework.security.context.DelegatingApplicationListener;
//import org.springframework.security.web.FilterChainProxy;
//import org.springframework.security.web.FilterInvocation;
//import org.springframework.security.web.SecurityFilterChain;
//import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
//
///**
// * Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web
// * based security for Spring Security. It then exports the necessary beans. Customizations
// * can be made to {@link WebSecurity} by implementing {@link WebSecurityConfigurer} and
// * exposing it as a {@link Configuration} or exposing a {@link WebSecurityCustomizer}
// * bean. This configuration is imported when using {@link EnableWebSecurity}.
// *
// * @author Rob Winch
// * @author Keesun Baik
// * @since 3.2
// * @see EnableWebSecurity
// * @see WebSecurity
// */
//@Configuration(proxyBeanMethods = false)
//public class CustomWebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
//
//	public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";
//	private CustomWebSecurity customWebSecurity;
//
//	private Boolean debugEnabled;
//
//	private List<SecurityConfigurer<Filter, CustomWebSecurity>> webSecurityConfigurers;
//
//	private List<SecurityFilterChain> securityFilterChains = Collections.emptyList();
//
//	private List<CustomWebSecurityCustomizer> webSecurityCustomizers = Collections.emptyList();
//
//	private ClassLoader beanClassLoader;
//
//	@Autowired(required = false)
//	private ObjectPostProcessor<Object> objectObjectPostProcessor;
//
//	@Autowired(required = false)
//	private HttpSecurity httpSecurity;
//
//	@Bean
//	public static DelegatingApplicationListener delegatingApplicationListener() {
//		return new DelegatingApplicationListener();
//	}
//
//	private EnumSet<DispatcherType> getDispatcherTypes(SecurityProperties securityProperties) {
//		if (securityProperties.getFilter().getDispatcherTypes() == null) {
//			return null;
//		}
//		return securityProperties.getFilter().getDispatcherTypes().stream()
//				.map((type) -> DispatcherType.valueOf(type.name()))
//				.collect(Collectors.toCollection(() -> EnumSet.noneOf(DispatcherType.class)));
//	}
//	@Bean
//	@DependsOn(CustomWebSecurityConfiguration.DEFAULT_FILTER_NAME)
//	public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler() {
//		return this.customWebSecurity.getExpressionHandler();
//	}
//
//
//
//	/**
//	 * Creates the Spring Security Filter Chain
//	 * @return the {@link Filter} that represents the security filter chain
//	 * @throws Exception
//	 * 创建 FilterChainProxy bean 名称为 springSecurityFilterChain
//	 *
//	 * SpringSecurity默认提供的过滤器链
//	 */
//	@Bean(name = CustomWebSecurityConfiguration.DEFAULT_FILTER_NAME)
//	public Filter customSpringSecurityFilterChain() throws Exception {
//
//		boolean hasFilterChain = !this.securityFilterChains.isEmpty();
//
//		// 如果过滤器链为null。那么就配置一个默认的
//		if (!hasFilterChain) {
//
//			// 添加过滤器链
//			this.customWebSecurity.addSecurityFilterChainBuilder(() -> {
//				this.httpSecurity.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated());
//				this.httpSecurity.formLogin(Customizer.withDefaults());
//				this.httpSecurity.httpBasic(Customizer.withDefaults());
//				return this.httpSecurity.build();
//			});
//		}
//
//
//
//		for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
//			// 添加过滤器链
//			this.customWebSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
//		}
//
//		for (CustomWebSecurityCustomizer customizer : this.webSecurityCustomizers) {
//			customizer.customize(this.customWebSecurity);
//		}
//
//		// 构建 FilterChainProxy 过滤器
//		return this.customWebSecurity.build();
//	}
//
//	/**
//	 * Creates the {@link WebInvocationPrivilegeEvaluator} that is necessary to evaluate
//	 * privileges for a given web URI
//	 * @return the {@link WebInvocationPrivilegeEvaluator}
//	 */
//	@Bean
//	@DependsOn(CustomWebSecurityConfiguration.DEFAULT_FILTER_NAME)
//	public WebInvocationPrivilegeEvaluator privilegeEvaluator() {
//		return this.customWebSecurity.getPrivilegeEvaluator();
//	}
//
//	/**
//	 * Sets the {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>}
//	 * instances used to create the web configuration.
//	 * @param objectPostProcessor the {@link ObjectPostProcessor} used to create a
//	 * {@link WebSecurity} instance
//	 * @param beanFactory the bean factory to use to retrieve the relevant
//	 * {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>} instances used to
//	 * create the web configuration
//	 * @throws Exception
//	 */
//	@Autowired(required = false)
//	public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor, ConfigurableListableBeanFactory beanFactory, RouterSingleFilterChain routerSingleFilterChain) throws Exception {
//		// 创建 webSecurity 对象
//		this.customWebSecurity = objectPostProcessor.postProcess(new CustomWebSecurity(objectPostProcessor,routerSingleFilterChain));
//		if (this.debugEnabled != null) {
//			this.customWebSecurity.debug(this.debugEnabled);
//		}
//
//
//		// 从spring 容器 获取 WebSecurityConfigurer 配置类
//		List<SecurityConfigurer<Filter, CustomWebSecurity>> webSecurityConfigurers = this.getWebSecurityConfigurers(beanFactory);
//
//		webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);
//
//		Integer previousOrder = null;
//		Object previousConfig = null;
//
//		for (SecurityConfigurer<Filter, CustomWebSecurity> config : webSecurityConfigurers) {
//
//			Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
//			if (previousOrder != null && previousOrder.equals(order)) {
//				throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of " + order
//						+ " was already used on " + previousConfig + ", so it cannot be used on " + config + " too.");
//			}
//			previousOrder = order;
//			previousConfig = config;
//		}
//
//		// 遍历 WebSecurityConfigurer 配置类
//		for (SecurityConfigurer<Filter, CustomWebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
//			// 添加 WebSecurityConfigurer 配置
//			this.customWebSecurity.apply(webSecurityConfigurer);
//		}
//		this.webSecurityConfigurers = webSecurityConfigurers;
//	}
//	@SuppressWarnings({ "rawtypes", "unchecked" })
//	private List<SecurityConfigurer<Filter, CustomWebSecurity>> getWebSecurityConfigurers(ConfigurableListableBeanFactory beanFactory) {
//
//		List<SecurityConfigurer<Filter, CustomWebSecurity>> webSecurityConfigurers = new ArrayList<>();
//
//		Map<String, WebSecurityConfigurer> beansOfType = beanFactory.getBeansOfType(WebSecurityConfigurer.class);
//		for (Map.Entry<String, WebSecurityConfigurer> entry : beansOfType.entrySet()) {
//			webSecurityConfigurers.add(entry.getValue());
//		}
//		return webSecurityConfigurers;
//	}
//
//	@Autowired(required = false)
//	void setFilterChains(List<SecurityFilterChain> securityFilterChains) {
//		this.securityFilterChains = securityFilterChains;
//	}
//
//	@Autowired(required = false)
//	void setWebSecurityCustomizers(List<CustomWebSecurityCustomizer> webSecurityCustomizers) {
//		this.webSecurityCustomizers = webSecurityCustomizers;
//	}
//
//	@Bean
//	public static BeanFactoryPostProcessor conversionServicePostProcessor() {
//		return new RsaKeyConversionServicePostProcessor();
//	}
//
//	@Override
//	public void setImportMetadata(AnnotationMetadata importMetadata) {
//		Map<String, Object> enableWebSecurityAttrMap = importMetadata.getAnnotationAttributes(EnableWebSecurity.class.getName());
//		AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap);
//		this.debugEnabled = enableWebSecurityAttrs.getBoolean("debug");
//		if (this.customWebSecurity != null) {
//			this.customWebSecurity.debug(this.debugEnabled);
//		}
//	}
//
//	@Override
//	public void setBeanClassLoader(ClassLoader classLoader) {
//		this.beanClassLoader = classLoader;
//	}
//
//
//	/**
//	 * A custom version of the Spring provided AnnotationAwareOrderComparator that uses
//	 * {@link AnnotationUtils#findAnnotation(Class, Class)} to look on super class
//	 * instances for the {@link Order} annotation.
//	 *
//	 * @author Rob Winch
//	 * @since 3.2
//	 */
//	private static class AnnotationAwareOrderComparator extends OrderComparator {
//
//		private static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
//
//		@Override
//		protected int getOrder(Object obj) {
//			return lookupOrder(obj);
//		}
//
//		private static int lookupOrder(Object obj) {
//			if (obj instanceof Ordered) {
//				return ((Ordered) obj).getOrder();
//			}
//			if (obj != null) {
//				Class<?> clazz = ((obj instanceof Class) ? (Class<?>) obj : obj.getClass());
//				Order order = AnnotationUtils.findAnnotation(clazz, Order.class);
//				if (order != null) {
//					return order.value();
//				}
//			}
//			return Ordered.LOWEST_PRECEDENCE;
//		}
//
//	}
//
//}
